package bsh;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import bsh.exception.CompilationFailedException;
import bsh.meta.JavaClassWrapper;
import bsh.meta.Scope;
import bsh.meta.TypeWrapper;

/**
 * Compiler para um {@link BSHThrowStatement}
 * 
 * @author takeshi
 */
public class ThrowNodeCompiler implements NodeCompiler {

    private final BSHThrowStatement node;

    private final CompilationUnit unit;

    /**
     * C'tor
     * 
     * @param node node
     * @param unit unit
     */
    public ThrowNodeCompiler(BSHThrowStatement node, CompilationUnit unit) {
        super();
        this.node = node;
        this.unit = unit;
    }

    /**
     * {@inheritDoc}
     */
    public void compile(MethodVisitor host, CompilationState state) throws CompilationFailedException {
        this.unit.compileNode(this.node.getChild(0), host, state);
        state.assertStackSize(1);
        TypeWrapper popStack = state.popStack();
        if (!JavaClassWrapper.wrapperFor(Exception.class).isSuperTypeOf(popStack)) {
            throw new CompilationFailedException(this.node.getLineNumber(), "cannot throw instance of type: " + popStack);
        }
        host.visitInsn(Opcodes.ATHROW);
    }

    /**
     * {@inheritDoc}
     */
    public TypeWrapper nodeResultType(Scope scope) throws CompilationFailedException {
        return JavaClassWrapper.VOID_WRAPPER;
    }

}
